home *** CD-ROM | disk | FTP | other *** search
/ Programmer Power Tools / Programmer Power Tools.iso / progjrn / pj_7_1.arc / WINH19.C < prev    next >
Text File  |  1988-10-23  |  13KB  |  521 lines

  1. /*
  2.  * Windows H19 emulator
  3.  * 
  4.  * Written by William S. Hall
  5.  *          3665 Benton Street, #66
  6.  *          Santa Clara, CA 95051
  7.  *
  8.  * Program entry module - extracts
  9.  */
  10.  
  11. /* Windows entry point */
  12. int FAR PASCAL WinMain(hInstance, hPrevInstance, lpszCmdLine, cmdShow)
  13. HANDLE hInstance, hPrevInstance;
  14. LPSTR lpszCmdLine;
  15. short cmdShow;
  16. {
  17.  
  18.   /* 
  19.    * Initialization
  20.    */
  21.     if (!InitProgram(hInstance,hPrevInstance, lpszCmdLine, cmdShow))
  22.     return FALSE;
  23.  
  24.   /* 
  25.    * Message loop
  26.    */
  27.     while (TRUE)
  28.     if (!DoMessage())    /* if message, process it */
  29.         ProcessComm();    /* if none, then take care of communications */
  30. }
  31.  
  32. /* 
  33.  * Main window procedure.  If the terminal is off-line, then Windows calls
  34.  * this function whenever it has information for the main window.
  35.  * If we are on-line, then the subclass window procedure below is
  36.  * entered first.  Any messages not processed there come here.
  37.  */
  38. long FAR PASCAL MainWndProc(hWnd,message,wParam,lParam)
  39. HWND hWnd;
  40. unsigned message;
  41. WORD wParam;
  42. LONG lParam;
  43. {
  44.  
  45.     PAINTSTRUCT ps;
  46.     BYTE ShortStr[2];
  47.     HMENU hMenu;
  48.  
  49.     switch(message) {
  50.  
  51.       /* 
  52.        * This action is required when the clipboard chain changes.
  53.        */
  54.        case WM_CHANGECBCHAIN:
  55.         if (wParam == hWndNext)
  56.         hWndNext = LOWORD(lParam);
  57.         SendMessage(hWndNext, message, wParam, lParam);
  58.         break;
  59.  
  60.       /* 
  61.        * Enable our 'paste' menu if there is textual data in clipboard.
  62.        */
  63.     case WM_DRAWCLIPBOARD:
  64.         if (IsWindow(hWndNext))
  65.         SendMessage(hWndNext, message, wParam, lParam);
  66.         if (OpenClipboard(hWnd)) {
  67.         hClipData = GetClipboardData(CF_TEXT);
  68.         hMenu = GetMenu(hWnd);
  69.         if (hClipData != NULL)
  70.             EnableMenuItem(hMenu, IDM_PASTE, MF_ENABLED);
  71.         else
  72.             EnableMenuItem(hMenu, IDM_PASTE, MF_GRAYED);
  73.         CloseClipboard();
  74.         }
  75.         break;
  76.  
  77.      /* 
  78.       * Main window has been created.  Do some initializations unique
  79.       *    to this window.
  80.       */
  81.     case WM_CREATE:
  82.         MainWndCreate(hWnd,lParam);
  83.         break;
  84.  
  85.      /* 
  86.       * The WM_KEYDOWN message gives us a way to process special keys
  87.       * such as those from the keypad or the function keys.  If we
  88.       * get this message, then the terminal is off-line.  Since we still
  89.       * want the keypad to perform correctly, i. e. up-arrow moves the
  90.       * cursor up, we call the local keydown routine to do the right thing.
  91.       */
  92.     case WM_KEYDOWN:
  93.         if (!CD.KeyboardDisabled)
  94.             H19LocalKeyDown(wParam);
  95.         break;
  96.  
  97.       /* 
  98.        * A key down/up stroke has been translated to a printable character.
  99.        * Since we are off-line, we simply process it locally.
  100.        */
  101.     case WM_CHAR:
  102.         if (!CD.KeyboardDisabled) {
  103.             ShortStr[0] = (BYTE)wParam;
  104.             H19StringInput(ShortStr,(short)1);
  105.         if (wParam == XON)
  106.             EscapeCommFunction(cid,SETXON);
  107.         }
  108.         break;
  109.  
  110.       /* 
  111.        *   We can create the caret.  Since the main window does not carry
  112.        * the text, the request is passed on to the currently active
  113.        * child, which may be the main window or the status line.
  114.        */
  115.     case WM_SETFOCUS:
  116.         CD.OwnCaret = TRUE;
  117.         if (IsWindowEnabled(hWnd) && IsWindow(hWndActive)) {
  118.         SendMessage(hWndActive, WH19_CARETFUNCTION, H19_CREATECARET,
  119.                 (LONG)CD.OwnCaret);
  120.         }
  121.         break;
  122.  
  123.       /* 
  124.        * We have lost input focus, so we must destroy the caret.  The 
  125.        * request is simply passed to the active child window.
  126.        */
  127.     case WM_KILLFOCUS:
  128.         if (IsWindow(hWndActive)) {
  129.         SendMessage(hWndActive,WH19_CARETFUNCTION,H19_DESTROYCARET,
  130.                 (LONG)CD.OwnCaret);
  131.         }
  132.         CD.OwnCaret = FALSE;
  133.         break;
  134.  
  135.       /* 
  136.        * A menu item or accelerator has been selected.  Process it.
  137.        */
  138.     case WM_COMMAND:
  139.         WndCommand(hWnd, wParam, lParam);
  140.         break;
  141.  
  142.       /* 
  143.        * The main window has moved.  Recompute some parameters to help
  144.        * us locate the child terminal windows.
  145.        */
  146.     case WM_MOVE:
  147.         MW.SCTopTextLine = HIWORD(lParam);
  148.         MW.SCBottomTextLine = MW.SCTopTextLine + MW.BottomTextLine;
  149.         break;
  150.  
  151.       /* 
  152.        * The main window has been resized.  We must now move the child
  153.        * windows accordingly.
  154.        */
  155.     case WM_SIZE:
  156.         SizeWindow(LOWORD(lParam), HIWORD(lParam), wParam);
  157.         break;
  158.  
  159.       /* 
  160.        * Close the comm port and get off the clipboard chain; exiting.
  161.        */
  162.     case WM_CLOSE:
  163.         CloseCommPort(hWnd, &cid);
  164.         ChangeClipboardChain(hWnd, hWndNext);
  165.         DestroyWindow(hWnd);
  166.         break;
  167.  
  168.       /* 
  169.        * Windows is exiting; close the comm port.
  170.        */
  171.     case WM_ENDSESSION:
  172.         if (wParam)
  173.             CloseCommPort(hWnd, &cid);
  174.         break;
  175.  
  176.       /* 
  177.        * Request to exit.
  178.        */
  179.     case WM_DESTROY:
  180.         PostQuitMessage(0);
  181.         break;
  182.  
  183.       /* 
  184.        * Clear main window if not iconic.  Otherwise draw icon.
  185.        */
  186.     case WM_PAINT:
  187.         BeginPaint(hWnd, (LPPAINTSTRUCT)&ps);
  188.         MainWndPaint(hWnd, ps.hdc);
  189.         EndPaint(hWnd, (LPPAINTSTRUCT)&ps);
  190.         break;
  191.  
  192.       /* 
  193.        * We watch this message for the 'About' box command.
  194.        */
  195.     case WM_SYSCOMMAND:
  196.             return((long)MainSysCommand(hWnd, message, wParam,lParam));
  197.  
  198.       /* 
  199.        * All messages we don't process go here.
  200.        */
  201.     default:
  202.         return ((long)DefWindowProc(hWnd,message,wParam,lParam));
  203.     }
  204.     return(0L);
  205. }
  206.  
  207. /* 
  208.  * Subclass window procedure.  This procedure is called first whenever
  209.  * the terminal is on-line.  Any message not processed here must be
  210.  * returned to the main window procedure above.
  211.  */
  212. LONG FAR PASCAL MainWndSubclassProc(hWnd, message, wParam, lParam)
  213. HWND hWnd;
  214. unsigned message;
  215. WORD wParam;
  216. LONG lParam;
  217. {
  218.  
  219.     BYTE outstr[80];
  220.     int len = 0;
  221.     BOOL CheckForControl = FALSE;
  222.  
  223.     switch(message) {
  224.  
  225.       /* 
  226.        * We are on-line and a printable character has been struck.
  227.        * Copy the character to a buffer.  See below for call to
  228.        * write to the communications port.
  229.        */
  230.     case WM_CHAR:
  231.         if (!CD.KeyboardDisabled)
  232.             outstr[len++] = (BYTE)wParam;
  233.             break;
  234.  
  235.      /* 
  236.       * We are on-line and a key-down code has been received.  We
  237.       *    use this message to process keypad and other special keys.
  238.       */
  239.     case WM_KEYDOWN:
  240.       /* set comm break if CTRL-BREAK is down */
  241.         if (wParam == VK_CANCEL) {
  242.         if (CD.BreakFlag == -1)
  243.             CD.BreakFlag = SetCommBreak(cid);
  244.              break;
  245.         }
  246.       /* 
  247.        * Use the scroll key to control scrolling or hold-screen mode.
  248.            */
  249.         else if (wParam == VK_SCROLL) {
  250.         SetScrollState();
  251.         break;
  252.         }
  253.         if (!CD.KeyboardDisabled) {
  254.         switch(wParam) {
  255.           /* 
  256.            * Translate CTRL-BKSP to a DELETE character.
  257.                    */
  258.             case VK_BACK:
  259.             if (GetKeyState(VK_CONTROL) & 0x8000)
  260.                 outstr[len++] = DEL;
  261.             break;
  262.  
  263.           /* 
  264.            * For the rest of the keypad keys, put together a
  265.            *  string (such as ESC A for up-arrow when in Heath
  266.            *  mode or ESC [ A when it ANSI mode).  In certain
  267.            *  cases, if the control key is also down, then the
  268.            *  string is not tranmitted as per H-19 behavior.
  269.            */
  270.             default:
  271.             CheckForControl = OutputKeydown(outstr, &len, wParam);
  272.             break;
  273.         }
  274.         }
  275.         break;        
  276.  
  277.        /* 
  278.         * All programmable function keys are in the resource accelerator
  279.     * table.  Hence they generate WM_COMMAND messages.  
  280.     * Since they have no effect unless on-line, we process them here.
  281.     */
  282.        case WM_COMMAND:
  283.         if ((wParam >= IDM_F1) && (wParam <= IDM_CSF12)) {
  284.             if (!CD.KeyboardDisabled) {
  285.             char *tptr;
  286.             int sparam, index;
  287.             sparam = (wParam /100) * 100;
  288.             index = wParam - sparam;
  289.             switch (sparam) {
  290.                 case IDM_F1:            /* unshifted */
  291.                 tptr = szFKey[index];
  292.                     break;
  293.                 case IDM_SF1:            /* shifted */
  294.                 tptr = szSFKey[index];
  295.                      break;
  296.             case IDM_CF1:            /* control */
  297.                 tptr = szCFKey[index];
  298.                     break;
  299.                 case IDM_CSF1:            /* control-shift */
  300.                 tptr = szCSFKey[index];
  301.                 break;
  302.             }
  303.         /* 
  304.          * Read programmed action from win.ini.
  305.                  */
  306.                 len = GetProfileString((LPSTR)szAppName,(LPSTR)tptr,
  307.                             (LPSTR)"",(LPSTR)outstr,80);
  308.         /* 
  309.          * Look for '\char' entries.  Convert them to control chars.
  310.          */
  311.             ScanForEscapes(outstr, &len);
  312.             break;        
  313.         }
  314.         break;
  315.         }
  316.      /* 
  317.           * All other WM_COMMAND messages are sent on to main wnd proc.
  318.           */
  319.         return(CallWindowProc(fpTerminal,hWnd,message,wParam,lParam));
  320.  
  321.     case WM_KEYUP:
  322.       /* 
  323.            * if CTRL-BREAK key is released, then clear comm break.
  324.            */
  325.         if (wParam == VK_CANCEL) {
  326.                 ClearCommBreak(cid);
  327.         CD.BreakFlag = -1;
  328.         break;
  329.         }
  330.  
  331.      /* 
  332.       * Unprocessed messages go here.
  333.       */
  334.     default:
  335.         return(CallWindowProc(fpTerminal,hWnd,message,wParam,lParam));
  336.  
  337.     }
  338.   /* 
  339.    * If CheckForControl is TRUE, then do not send string to comm
  340.    * port.  Instead, return it to main window procedure where it
  341.    * can be processed as if off-line.
  342.    */
  343.     if (CheckForControl)
  344.     if (GetKeyState(VK_CONTROL) & 0x8000)
  345.         return(CallWindowProc(fpTerminal,hWnd,message,wParam,lParam));
  346.   /* 
  347.    * We have a string of positive length, so send it out.
  348.    */
  349.    if (len) {
  350.     WriteToPort(cid, (BYTE FAR *)outstr, len);
  351.      /* 
  352.       * Local echo, so send it back to ourselves as well.
  353.       */
  354.     if (!CD.FullDuplex)
  355.         return(CallWindowProc(fpTerminal,hWnd,message,wParam,lParam));
  356.     }
  357.     return 0L;
  358. }
  359.  
  360. /* 
  361.  * This routine builds the appropriate string for the keypad keys.
  362.    TRUE is returned if the key is one which is not sent if the
  363.    control key is pressed.
  364.  */
  365. static BOOL NEAR OutputKeydown(BYTE str[], int *plen, WORD wparam)
  366. {
  367.  
  368.     BOOL result = FALSE;
  369.     int index;
  370.     BOOL shift, control;
  371.  
  372.   /* 
  373.    * If Heath mode, then prefix string with ESC.  If ANSI, add '[' or
  374.    * other appropriate lead character.
  375.    */
  376.     str[(*plen)++] = ESC;
  377.     if (CD.ANSIMode)
  378.     str[(*plen)++] = '[';
  379.  
  380.     switch(wparam) {
  381.         case VK_UP:            /* Up arrow */
  382.         str[(*plen)++] = 'A';
  383.         result = TRUE;            
  384.         break;
  385.         case VK_DOWN:            /* Down arrow */
  386.         str[(*plen)++] = 'B';
  387.         result = TRUE;            
  388.         break;
  389.     case VK_RIGHT:            /* Right arrow */
  390.         str[(*plen)++] = 'C';
  391.         result = TRUE;            
  392.         break;
  393.     case VK_LEFT:            /* Left arrow */
  394.         str[(*plen)++] = 'D';
  395.         result = TRUE;            
  396.         break;
  397.       /* 
  398.        * Home key.  On H-19 this is toggle insert character.
  399.        */
  400.     case VK_HOME:            
  401.         if (CD.ANSIMode) {
  402.         str[(*plen)++] = '4';
  403.             if (CD.ICToggle)
  404.             str[(*plen)++] = 'l';
  405.             else
  406.             str[(*plen)++] = 'h';
  407.         }
  408.         else {
  409.             if (CD.ICToggle)
  410.             str[(*plen)++] = 'O';
  411.             else
  412.             str[(*plen)++] = '@';
  413.         }
  414.         result = TRUE;
  415.         break;
  416.       /* 
  417.        * End key.  On H-19, this is insert-line.
  418.        */
  419.     case VK_END:
  420.         str[(*plen)++] = 'L';
  421.         result = TRUE;            
  422.         break;
  423.       /* 
  424.        * Pg Up key.  On H-19, this is delete character.
  425.        */
  426.     case VK_PRIOR:
  427.         if (CD.ANSIMode)
  428.             str[(*plen)++] = 'P';
  429.         else
  430.             str[(*plen)++] = 'N';
  431.         result = TRUE;
  432.         break;
  433.       /* 
  434.        * Pg Dn key.  On H-19, this is delete-line.
  435.        */
  436.     case VK_NEXT:
  437.         str[(*plen)++] = 'M';
  438.         result = TRUE;            
  439.         break;
  440.       /* 
  441.        * '5' key.  On H-19, this is the home key.
  442.        */
  443.     case VK_CLEAR:
  444.         str[(*plen)++] = 'H';
  445.         result = TRUE;            
  446.         break;
  447.  
  448.       /* 
  449.        * Function keys.  F1 to F5 correspond on H-19.  F6 acts as
  450.        * the erase key.  F7, F8, and F9 are the blue, red, white
  451.        * keys, respectively.
  452.        */
  453.     case VK_F1:
  454.     case VK_F2:
  455.     case VK_F3:
  456.     case VK_F4:
  457.     case VK_F5:
  458.     case VK_F7:
  459.     case VK_F8:
  460.     case VK_F9:
  461.         if (wparam >= VK_F7)
  462.             index = 'P' + wparam - VK_F7;
  463.         else
  464.             index = 'S' + wparam - VK_F1;
  465.         if (CD.ANSIMode)
  466.             str[*plen - 1] = 'O';
  467.         str[(*plen)++] = (BYTE)index;
  468.         break;
  469.  
  470.       /* 
  471.        * Erase key.  Do different things if shifted or not.
  472.        */
  473.     case VK_F6:
  474.         if (GetKeyState(VK_SHIFT) & 0x8000) {
  475.         if (CD.ANSIMode) {
  476.              str[(*plen)++] = '2';
  477.              str[(*plen)++] = 'J';
  478.         }
  479.         else
  480.             str[(*plen)++] = 'E';
  481.         }
  482.         else
  483.             str[(*plen)++] = 'J';
  484.         result = TRUE;
  485.         break;
  486.  
  487.       /* 
  488.        * If we get these keys, then we have to send out 3-character
  489.        * sequences if in Alternate keypad mode.
  490.        */
  491.     case VK_NUMPAD0:
  492.     case VK_NUMPAD1:
  493.     case VK_NUMPAD2:
  494.     case VK_NUMPAD3:
  495.     case VK_NUMPAD4:
  496.     case VK_NUMPAD5:
  497.     case VK_NUMPAD6:
  498.     case VK_NUMPAD7:
  499.     case VK_NUMPAD8:
  500.     case VK_NUMPAD9:
  501.     case VK_DECIMAL:
  502.         if (CD.AltKeypad) {
  503.         if (CD.ANSIMode)
  504.             str[*plen - 1] = 'O';
  505.         else
  506.             str[(*plen)++] = '?';
  507.         if (wparam == VK_DECIMAL)
  508.             str[(*plen)++] = 'n';
  509.         else
  510.                 str[(*plen)++] = (BYTE)('p' + (wparam - VK_NUMPAD0));
  511.         }
  512.         else
  513.         *plen = 0;
  514.         break;
  515.     default:
  516.         *plen = 0;
  517.         break;
  518.     }
  519.     return(result);
  520. }
  521.